feat(launch): implement Xiuper launch animation with design system#497
feat(launch): implement Xiuper launch animation with design system#497
Conversation
## Summary Implement the Xiuper launch animation for Desktop app based on the design system specification (xuiper-ds.md). ## Changes ### New Files - AutoDevAnimation.kt: Animation curves and timing constants - EaseXiu: cubic-bezier(0.16, 1, 0.3, 1) - ultra-fast response - EaseStream: linear - for AI code streaming - SpringTactile: bounce effect for micro-interactions - Duration constants for Launch animation phases - XiuperLaunchScreen.kt: Complete launch animation component - 6-phase animation state machine - Multi-layer glow effects (AI purple + Xiu cyan) - Speed lines for forward momentum visual - Breathing pulse animation - Reduced-motion accessibility support ### Modified Files - Platform.kt (all platforms): Added prefersReducedMotion() function - JVM: macOS/Windows/Linux system settings detection - Android: Settings.Global accessibility check - JS: prefers-reduced-motion media query - iOS: UIAccessibility.isReduceMotionEnabled - WASM: Returns false (no system access) - Main.kt: Integrated launch screen with splash state management - --skip-splash command line argument support - ThemeManager.ThemeMode.DARK for launch screen ## Animation Timeline (2.2s total) - [0-100ms] Initial delay - 'gathering power' - [100-500ms] Glow expansion - energy gathering - [500-1000ms] Logo scale up with ease-xiu curve - [1000-1300ms] Text slide in from below - [1300-1900ms] Brand display + breathing glow - [1900-2200ms] Fade out to main interface ## Design System Alignment - Neon-Noir aesthetic with Void background (#0B0E14) - Dual-color energy system (xiu cyan + ai purple) - Speed lines for 'Forward Momentum' - Breathing glow for 'never static' principle Closes #493
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds a cross-platform API Platform.prefersReducedMotion() and implements Xiuper launch animation primitives and composable. Platform implementations vary by target (Android stub, iOS/JS/JVM/WASM platform checks). Desktop JVM startup integrates the splash flow with a --skip-splash flag and reduced-motion consideration. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR implements a comprehensive launch animation system for the Xiuper Desktop app, introducing a design system-aligned animation framework with multi-platform accessibility support. The implementation adds sophisticated visual effects (dual-color glows, speed lines, breathing pulse) while respecting user accessibility preferences across all platforms.
Key Changes:
- Introduces
AutoDevAnimationsystem with specialized easing curves (EaseXiu, EaseStream, SpringTactile) aligned with "唯快不破" design philosophy - Implements 6-phase launch animation (2.2s total) with reduced-motion fallback for accessibility
- Adds
Platform.prefersReducedMotion()with platform-specific implementations (macOS, Windows, Linux, Android, iOS, JS, WASM)
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt |
New animation system defining easing curves (EaseXiu, EaseStream, SpringTactile) and timing constants for the Xiuper design system |
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt |
Complete launch screen with 6-phase animation, multi-layer glow effects, speed lines, and reduced-motion support |
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt |
Integrates launch screen with splash state management and --skip-splash command line argument |
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.kt |
Adds prefersReducedMotion() function to Platform interface for accessibility |
mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt |
Implements reduced motion detection for macOS, Windows, and Linux desktop platforms |
mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.kt |
Android implementation for reduced motion detection (has implementation issue) |
mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt |
iOS implementation using UIAccessibility.isReduceMotionEnabled |
mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.kt |
JavaScript implementation using prefers-reduced-motion media query |
mpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt |
WebAssembly stub returning false (no system access) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Android: Check if animations are disabled in accessibility settings | ||
| // Note: This requires Context which we don't have here | ||
| // In a real implementation, this would check Settings.Global.ANIMATOR_DURATION_SCALE | ||
| // For now, return false as default | ||
| return try { | ||
| // Check if animator duration scale is 0 (animations disabled) | ||
| val animatorDurationScale = android.provider.Settings.Global.getFloat( | ||
| null, // ContentResolver - not available without Context | ||
| android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, | ||
| 1.0f | ||
| ) | ||
| animatorDurationScale == 0f | ||
| } catch (e: Exception) { | ||
| false | ||
| } |
There was a problem hiding this comment.
The Android implementation will always fail because Settings.Global.getFloat() requires a non-null ContentResolver as the first parameter, but null is being passed. This will cause a NullPointerException at runtime.
Consider using a different approach for Android, such as:
- Pass a Context parameter through the Platform interface when needed for UI-related functions
- Return
falseas default for now and document this limitation - For the Desktop app use case (JVM), this won't be an issue, but if Android support is planned, this needs to be addressed.
| // Android: Check if animations are disabled in accessibility settings | |
| // Note: This requires Context which we don't have here | |
| // In a real implementation, this would check Settings.Global.ANIMATOR_DURATION_SCALE | |
| // For now, return false as default | |
| return try { | |
| // Check if animator duration scale is 0 (animations disabled) | |
| val animatorDurationScale = android.provider.Settings.Global.getFloat( | |
| null, // ContentResolver - not available without Context | |
| android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, | |
| 1.0f | |
| ) | |
| animatorDurationScale == 0f | |
| } catch (e: Exception) { | |
| false | |
| } | |
| // Android: Checking for reduced motion requires a Context to access ContentResolver. | |
| // This implementation does not have access to Context, so we cannot check the setting. | |
| // Always return false as default and document this limitation. | |
| return false |
| osName.contains("windows") -> { | ||
| // Windows: Check if animations are disabled via system property | ||
| // This is a simplified check; full implementation would use JNA/JNI | ||
| System.getProperty("swing.aatext", "false") == "false" && | ||
| System.getProperty("awt.useSystemAAFontSettings", "") == "off" |
There was a problem hiding this comment.
The Windows accessibility check logic appears incorrect. The code checks if swing.aatext is "false" AND awt.useSystemAAFontSettings is "off" to determine if animations should be reduced. These properties are related to font anti-aliasing, not animation preferences.
For proper Windows reduced motion detection, you would need to check:
SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, ...)via JNA/JNI- Or check Windows registry:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\DisableAnimations
The current implementation will likely always return false regardless of the user's actual animation preferences on Windows.
| * | ||
| * 特性:匀速,无加速减速 | ||
| * 用途:AI 代码生成的打字机效果 | ||
| * 原理:变与不确定的生成速度会让人感到卡顿, |
There was a problem hiding this comment.
Minor spelling issue: "原理:变与不确定的生成速度" should likely be "原理:可变与不确定的生成速度" (adding the character "可" for clarity, meaning "variable and uncertain generation speed").
| * 原理:变与不确定的生成速度会让人感到卡顿, | |
| * 原理:可变与不确定的生成速度会让人感到卡顿, |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt (1)
60-68: Add timeout to prevent indefinite blocking on macOS.
process.waitFor()can block indefinitely if thedefaultscommand hangs. Consider adding a timeout to prevent potential UI freezes during startup.osName.contains("mac") -> { // Check macOS reduce motion setting via defaults command val process = ProcessBuilder("defaults", "read", "com.apple.universalaccess", "reduceMotion") .redirectErrorStream(true) .start() val result = process.inputStream.bufferedReader().readText().trim() - process.waitFor() + val completed = process.waitFor(1, java.util.concurrent.TimeUnit.SECONDS) + if (!completed) { + process.destroyForcibly() + return false + } result == "1" }mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt (1)
69-69: Consider cachingprefersReducedMotion()result.On JVM/macOS,
Platform.prefersReducedMotion()spawns an external process. While the splash only shows once, recomposition during animation could call this multiple times. Consider caching withremember:+ val reducedMotion = remember { Platform.prefersReducedMotion() } + // 显示启动动画或主界面 if (showSplash) { AutoDevTheme(themeMode = ThemeManager.ThemeMode.DARK) { XiuperLaunchScreen( onFinished = { showSplash = false AutoDevLogger.info("AutoDevMain") { "✨ Launch animation completed" } }, - reducedMotion = Platform.prefersReducedMotion() + reducedMotion = reducedMotion ) }mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt (1)
147-158: Phase state access in coroutine loops may cause timing issues.The
while (phase < 5)loops inLaunchedEffectreadphasewhich is amutableStateOfvar. While Compose state is thread-safe for reads, the coroutine may not immediately observe state changes, potentially causing extra loop iterations after phase transitions.Consider using
snapshotFlowor breaking out of the loop when phase changes:LaunchedEffect(phase) { if (phase >= 1 && phase < 5) { var time = 0f - while (phase < 5) { + while (true) { + if (phase >= 5) break time += 0.03f glowPulse = (sin(time * 2) * 0.25f + 0.75f) delay(16) } } }mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt (2)
59-87: Consider adding explicit return types forSpringTactile.spec/SpringGentle.specMinor API clarity nit: giving these helpers an explicit return type (e.g., the spring spec type) would make their contract clearer at call sites and in IDE tooltips, without changing behavior.
-import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.SpringSpec @@ - fun <T> spec() = spring<T>( + fun <T> spec(): SpringSpec<T> = spring( @@ - fun <T> spec() = spring<T>( + fun <T> spec(): SpringSpec<T> = spring(
93-116: DeriveLaunch.TOTALfrom its phase constants to avoid driftRight now
TOTALis a hard-coded 2200ms that happens to match the sum of the phase durations. Deriving it from the components would prevent subtle bugs if any phase timing changes later.object Launch { const val INITIAL_DELAY = 100 // 初始延迟,营造"蓄力"感 const val GLOW_EXPAND = 400 // 光晕扩散(先于 Logo) const val LOGO_SCALE = 500 // Logo 放大 const val TEXT_SLIDE = 300 // 文字滑入 const val GLOW_PULSE = 600 // 光晕呼吸停留(更长的品牌展示) const val FADE_OUT = 300 // 淡出(更优雅的过渡) - const val TOTAL = 2200 // 总时长(让用户看清品牌) + const val TOTAL = + INITIAL_DELAY + + GLOW_EXPAND + + LOGO_SCALE + + TEXT_SLIDE + + GLOW_PULSE + + FADE_OUT // 总时长(让用户看清品牌) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.kt(1 hunks)mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.kt(1 hunks)mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt(2 hunks)mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.kt(1 hunks)mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt(1 hunks)mpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt(1 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt(1 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt(1 hunks)mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
**/*.kt: Useexpect/actualfor platform-specific code in Kotlin Multiplatform projects
For @JsExport in Kotlin, use concrete classes (not interfaces) and Promise (not Flow) for JavaScript interoperability
Avoid emoji and UTF-8 characters in WASM code
Files:
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.ktmpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.ktmpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.ktmpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.ktmpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.ktmpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.ktmpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt
🧠 Learnings (2)
📚 Learning: 2025-12-06T13:54:33.558Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T13:54:33.558Z
Learning: Applies to **/*.kt : Use `expect`/`actual` for platform-specific code in Kotlin Multiplatform projects
Applied to files:
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.ktmpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.ktmpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.ktmpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.ktmpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt
📚 Learning: 2025-12-06T13:54:33.558Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T13:54:33.558Z
Learning: Applies to **/*Compose*.kt : For Compose UI design, use `AutoDevColors` or `MaterialTheme.colorScheme`
Applied to files:
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt
🧬 Code graph analysis (1)
mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt (6)
mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.kt (1)
getOSName(15-17)mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.kt (1)
getOSName(14-14)mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt (1)
getOSName(19-21)mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.kt (1)
getOSName(13-15)mpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt (1)
getOSName(13-15)mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/PlatformExports.kt (1)
getOSName(21-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Agent
- GitHub Check: Test mpp-core (KMP)
- GitHub Check: Build
🔇 Additional comments (8)
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.kt (1)
30-35: LGTM!The
expectdeclaration follows the established pattern and includes clear documentation explaining its accessibility purpose. This properly enables platform-specific implementations as per Kotlin Multiplatform conventions.mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt (1)
48-51: LGTM!The iOS implementation correctly uses
UIAccessibility.isReduceMotionEnabled, which is the proper system API for detecting reduced motion preferences.mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.kt (1)
67-81: LGTM!The implementation correctly checks for browser environment before accessing
window.matchMedia, uses the standardprefers-reduced-motion: reducemedia query, and safely falls back tofalsefor Node.js or on exceptions.mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt (1)
62-71: LGTM - Launch screen integration is well-structured.The splash flow correctly:
- Wraps in
AutoDevThemewith dark mode for brand consistency- Passes reduced motion preference to
XiuperLaunchScreen- Logs completion and transitions to main UI via state change
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt (2)
280-285: Verify brand name spelling: "Xuiper" vs "Xiuper".The PR title and documentation reference "Xiuper" but the logo displays "Xuiper". Please confirm the intended spelling for brand consistency.
56-85: Well-implemented multi-phase animation with accessibility support.The state machine cleanly orchestrates the 6-phase animation sequence:
- Proper reduced motion support that bypasses animation entirely
- Timing constants sourced from
AutoDevAnimation.Duration.Launch- Clear phase transitions with appropriate delays
The implementation aligns well with the design system specification.
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt (2)
9-54: Easing presets and documentation are coherent with the Xiuper specThe three easing curves are well-chosen, documented, and match the described motion system; this should make reuse across the app straightforward.
122-138: Tween helpers nicely centralize motion semanticsThe
tweenXiu,tweenStream, andtweenStandardhelpers give a clean, reusable surface for consistent motion across the app; defaults tied to yourDurationpresets are sensible.
|
augment review |
Use kotlin.math.PI for angle conversion to improve consistency.
| WindowPlacement.Maximized | ||
| } | ||
| } | ||
| reducedMotion = Platform.prefersReducedMotion() |
There was a problem hiding this comment.
Calling Platform.prefersReducedMotion() synchronously inside composition can block the UI thread (macOS branch spawns a ProcessBuilder and waits), risking startup jank or a freeze. Consider resolving this off the UI thread and caching the value before composition (also aligns with EDT best practices) (Guideline: edt_violations).
🤖 Was this useful? React with 👍 or 👎
| .alpha(logoAlpha) | ||
| ) { | ||
| Text( | ||
| text = "Xuiper", |
There was a problem hiding this comment.
User-facing brand string uses "Xuiper" while the PR/design system refer to "Xiuper"; this inconsistency can confuse users. Consider aligning the displayed text with the intended brand spelling (also applies to the other occurrence in the subtitle).
🤖 Was this useful? React with 👍 or 👎
| letterSpacing = 4.sp, // 增加字间距,更有科技感 | ||
| color = AutoDevColors.Text.secondary, | ||
| modifier = Modifier | ||
| .offset { IntOffset(0, textOffset.toInt()) } |
There was a problem hiding this comment.
Modifier.offset { IntOffset(...) } expects pixel units, but the comment and animation treat 30 as dp; mixing dp intent with px values will look off on high-DPI displays. Consider using a dp-based offset or converting dp to px via density to keep consistent spacing across densities.
🤖 Was this useful? React with 👍 or 👎
Refine platform-specific prefersReducedMotion implementations for better accuracy and performance. Also correct "Xuiper" to "Xiuper" in UI text.
Replace deprecated UIAccessibility.isReduceMotionEnabled with UIAccessibilityIsReduceMotionEnabled for prefersReducedMotion detection.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt (1)
36-39: Consider movingprefersReducedMotion()call outside of composition.While caching via
rememberprevents repeated calls, the initial call still occurs during composition on the UI thread. On macOS, this spawns aProcessBuilderwith a 1-second timeout, which could cause startup jank.Consider initializing this before
application {}:+ // Cache reduced motion preference before composition to avoid blocking UI thread + val reducedMotion = Platform.prefersReducedMotion() + application { val trayState = rememberTrayState() var isWindowVisible by remember { mutableStateOf(true) } var triggerFileChooser by remember { mutableStateOf(false) } // 启动动画状态 var showSplash by remember { mutableStateOf(!skipSplash) } - // Cache prefersReducedMotion result to avoid repeated system calls - val reducedMotion = remember { Platform.prefersReducedMotion() }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.kt(1 hunks)mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt(2 hunks)mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt(1 hunks)mpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt(1 hunks)mpp-idea/src/test/kotlin/cc/unitmesh/devins/idea/renderer/JewelRendererTest.kt(1 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt(1 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt(1 hunks)mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt(3 hunks)
✅ Files skipped from review due to trivial changes (1)
- mpp-idea/src/test/kotlin/cc/unitmesh/devins/idea/renderer/JewelRendererTest.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
**/*.kt: Useexpect/actualfor platform-specific code in Kotlin Multiplatform projects
For @JsExport in Kotlin, use concrete classes (not interfaces) and Promise (not Flow) for JavaScript interoperability
Avoid emoji and UTF-8 characters in WASM code
Files:
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.ktmpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.ktmpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.ktmpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt
🧠 Learnings (2)
📚 Learning: 2025-12-06T13:54:33.558Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T13:54:33.558Z
Learning: Applies to **/*Compose*.kt : For Compose UI design, use `AutoDevColors` or `MaterialTheme.colorScheme`
Applied to files:
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt
📚 Learning: 2025-12-06T13:54:33.558Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T13:54:33.558Z
Learning: Applies to **/*.kt : Use `expect`/`actual` for platform-specific code in Kotlin Multiplatform projects
Applied to files:
mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.ktmpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt
🧬 Code graph analysis (2)
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt (4)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevTheme.kt (2)
AutoDevTheme(114-141)AutoDevTheme(146-159)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt (1)
XiuperLaunchScreen(56-301)mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/desktop/DesktopWindowLayout.kt (1)
DesktopWindowLayout(24-46)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/AutoDevApp.kt (1)
AutoDevApp(34-68)
mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt (6)
mpp-core/src/iosMain/kotlin/cc/unitmesh/agent/Platform.ios.kt (1)
getOSName(19-21)mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.kt (1)
getOSName(15-17)mpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt (1)
getOSName(13-15)mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/Platform.kt (1)
getOSName(14-14)mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/Platform.js.kt (1)
getOSName(13-15)mpp-core/src/jsMain/kotlin/cc/unitmesh/agent/PlatformExports.kt (1)
getOSName(21-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test mpp-core (KMP)
- GitHub Check: Build
🔇 Additional comments (13)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/theme/AutoDevAnimation.kt (4)
1-53: LGTM! Well-structured animation system.The animation curves are correctly defined and align with the design system requirements. The
EaseXiucurve (cubic-bezier(0.16, 1, 0.3, 1)) matches the specification for ultra-fast response, and the organization with clear documentation is excellent.
66-87: LGTM!Spring animation specs are well-defined with appropriate damping ratios and stiffness values for tactile feedback and gentle transitions.
93-116: LGTM!Duration constants are well-organized. The Launch sequence timings correctly sum to the declared
TOTALof 2200ms, matching the PR objectives.
122-139: LGTM!Preset animation spec functions provide a clean API for common animation patterns.
mpp-core/src/wasmJsMain/kotlin/cc/unitmesh/agent/Platform.wasmJs.kt (1)
45-58: LGTM!The WASM implementation correctly uses browser interop to query the
prefers-reduced-motionmedia query, with appropriate browser environment detection and error handling.mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/Platform.kt (1)
49-54: Acknowledged limitation with proper documentation.The stub implementation returning
falseis appropriate given the architectural constraint thatPlatformis a static object withoutContextaccess. The TODO comment clearly documents the path forward for future improvement.mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/Main.kt (2)
63-73: LGTM!The splash screen integration is clean with proper dark theme application and completion callback handling.
74-140: LGTM!The main UI structure is well-organized with proper state management and callback wiring.
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/launch/XiuperLaunchScreen.kt (4)
56-85: LGTM! Well-implemented animation state machine.The phase-based animation sequence with proper reduced-motion support is well-designed. The reduced-motion path correctly bypasses the full animation with a brief brand display.
147-170: LGTM!The animation loops are correctly implemented with proper termination conditions and frame timing.
178-270: LGTM!Canvas rendering for the multi-layer glow effects is well-implemented with proper use of design system colors and phase-based visibility.
273-299: LGTM!The logo and text section is correctly implemented. The brand spelling is consistent ("Xiuper"), and the offset animation properly uses dp units via
textOffset.dp.mpp-core/src/jvmMain/kotlin/cc/unitmesh/agent/Platform.jvm.kt (1)
52-89: LGTM with noted limitations.The implementation correctly handles each OS:
- macOS: Properly reads the
reduceMotionsetting with a 1-second timeout- Windows: Documented as requiring JNA/JNI for proper implementation, safely returns
false- Linux: Checks
GTK_ENABLE_ANIMATIONSenvironment variableThe blocking nature on macOS is a trade-off for functionality. This is cached once at startup via
remember { Platform.prefersReducedMotion() }in Main.kt (line 39), avoiding repeated system calls during runtime.
Simplifies reduced motion detection for WASM by always returning false due to media query limitations.
Summary
Implement the Xiuper launch animation for Desktop app based on the design system specification (xuiper-ds.md).
Changes
New Files
AutoDevAnimation.kt: Animation curves and timing constants
EaseXiu:cubic-bezier(0.16, 1, 0.3, 1)- ultra-fast responseEaseStream: linear - for AI code streamingSpringTactile: bounce effect for micro-interactionsXiuperLaunchScreen.kt: Complete launch animation component
Modified Files
Platform.kt (all platforms): Added
prefersReducedMotion()functionprefers-reduced-motionmedia queryUIAccessibility.isReduceMotionEnabledMain.kt: Integrated launch screen with splash state management
--skip-splashcommand line argument supportThemeManager.ThemeMode.DARKfor launch screenAnimation Timeline (2.2s total)
Design System Alignment
Based on
docs/design-system/xuiper-ds.md:#0B0E14)#00F3FF) + AI purple (#D946EF)prefers-reduced-motionsystem settingScreenshots
Launch animation with multi-layer glow effects and speed lines
Closes #493
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.